home *** CD-ROM | disk | FTP | other *** search
- /* 3DVto2D.c - convert 3DV data to 2-D list format */
-
- /* Oscar Garcia <garciao@mof.govt.nz>, May 1992 */
-
- /* uses getopt */
- int getopt(int argc, char *argv[], char *options);
- extern int optind;
- extern char *optarg;
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
-
- #define USAGE "usage: 3DVto2D [/tx] [/nx] [/dx] [input_file [output_file]]\n\
- \tIf file names are omitted, the standard i/o streams are used.\n\
- \tOptions (with defaults):\n\
- \t\t/t0 - Latitude, degrees\n\
- \t\t/n0 - Longitude, degrees\n\
- \t\t/d-3 - Viewing distance. Zero gives orthogonal projection.\n\
- \t\t Positive is in user units to object center.\n\
- \t\t Negative is relative to object size.\n\
- \t\t Default -3 is as in 3dv."
-
- #define ERROR(msg) {fputs(msg,stderr),exit(1);}
- #define PERROR(msg) {perror(msg),exit(1);}
-
- #define BIG 3e33
- #define EPS 1e-9
- #define RADIANS 3.141592/180
- #define DDEFAULT -3
-
- void main(int argc, char* argv[])
- {
- int i, j, n;
- double scale, slon, clon, slat, clat, t[3][3],
- lat = 0, lon = 0, dist = DDEFAULT;
- char options[] = "t:n:d:";
- FILE *infile = stdin, *outfile = stdout;
- typedef double POINT[3];
- POINT min, max, centre, xx, *x;
-
-
- /* get options */
- while ((n = getopt(argc, argv, options)) != EOF)
- if (n == '?')
- ERROR(USAGE)
- else
- switch (n)
- { case 't': lat = atof(optarg); break;
- case 'n': lon = atof(optarg); break;
- case 'd': dist = atof(optarg); break;
- }
-
- /* open files */
- if (optind < argc - 2)
- ERROR(USAGE); /* too many */
- if (optind < argc)
- { infile = fopen(argv[optind], "rt");
- if (infile == NULL)
- ERROR("Can't open input file");
- if (++optind < argc)
- { outfile = fopen(argv[optind], "wt");
- if (outfile == NULL)
- ERROR("Can't open output file");
- }
- }
-
- /* read points */
- i = fscanf(infile, "%d", &n);
- if (i != 1 || ferror(infile))
- PERROR("Bad input file");
- #ifdef __MSDOS__
- if ((unsigned)n * sizeof(POINT) > 0xfff0U)
- ERROR("64k memory block limit exceeded");
- #endif
- x = malloc((unsigned)n * sizeof(POINT));
- if (x == NULL)
- ERROR("Out of memory");
- for (j = 0; j < 3; j++)
- { min[j] = BIG;
- max[j] = -BIG;
- }
- for (i = 0; i < n; i++)
- { fscanf(infile, "%lf %lf %lf", &x[i][0], &x[i][1], &x[i][2]);
- for (j = 0; j < 3; j++)
- { if (x[i][j] < min[j])
- min[j] = x[i][j];
- else if (x[i][j] > max[j])
- max[j] = x[i][j];
- }
- }
- if (ferror(infile))
- PERROR("Error reading input");
-
- /* get centre and distance */
- for (j = 0, scale = 0.0; j < 3; j++)
- { centre[j] = (min[j] + max[j]) / 2;
- scale = scale + (max[j] - min[j]) * (max[j] - min[j]);
- }
- if (dist < -EPS) /* perspective, relative dist; convert to absolute */
- dist *= sqrt(scale * (1 + 0.25 / (dist * dist))) / -0.99;
-
- /* transformation matrix */
- slon = sin(lon * RADIANS);
- clon = cos(lon * RADIANS);
- slat = sin(lat * RADIANS);
- clat = cos(lat * RADIANS);
- t[0][0] = clon;
- t[0][1] = - slon;
- t[1][0] = clat * slon;
- t[1][1] = clat * clon;
- t[1][2] = slat;
- t[2][0] = - slat * slon;
- t[2][1] = - slat * clon;
- t[2][2] = clat;
-
- /* rotate and project along y */
- min[0] = min[2] = BIG; /* 2-d coords will be saved in 0 and 2 */
- max[0] = max[2] = -BIG;
- for (i = 0; i < n; i++)
- { for (j = 0; j < 3; j++)
- xx[j] = x[i][j] - centre[j];
- x[i][0] = t[0][0] * xx[0] + t[0][1] * xx[1];
- x[i][1] = t[1][0] * xx[0] + t[1][1] * xx[1] + t[1][2] * xx[2];
- x[i][2] = t[2][0] * xx[0] + t[2][1] * xx[1] + t[2][2] * xx[2];
- if (dist > EPS) /* perspective */
- { x[i][0] /= 1 - x[i][1] / dist;
- x[i][2] /= 1 - x[i][1] / dist;
- } /* x[i][1] not used again here, but might need it some day */
- if (x[i][0] < min[0])
- min[0] = x[i][0];
- else if (x[i][0] > max[0])
- max[0] = x[i][0];
- if (x[i][2] < min[2])
- min[2] = x[i][2];
- else if (x[i][2] > max[2])
- max[2] = x[i][2];
- }
-
- /* factor for scaling to [-1, 1] */
- scale = max[0];
- if (-min[0] > scale)
- scale = -min[0];
- if (max[2] > scale)
- scale = max[2];
- if (-min[2] > scale)
- scale = -min[2];
- scale = 1 / scale;
-
- /* output info */
- fscanf(infile, "%d", &n);
- fprintf(outfile, "# n=%d scale=%g x_range=[%g:%g] y_range=[%g:%g]\n",
- n, 1/scale, scale*min[0], scale*max[0], scale*min[2], scale*max[2]);
- fprintf(outfile, "# latitude=%g longitude=%g distance=%g\n",
- lat, lon, dist);
-
- /* output data */
- while (n-- > 0)
- { fscanf(infile, "%d %d", &i, &j);
- if (j == 0)
- putc('\n', outfile); /* blank line (move) */
- fprintf(outfile, "%g %g %d\n",
- scale * x[i-1][0], scale * x[i-1][2], j);
- }
- if (ferror(infile))
- PERROR("Error reading input");
- if (feof(infile))
- ERROR("Unexpected end of file on input");
- fclose(infile);
- if (ferror(outfile))
- PERROR("Error during output");
- fclose(outfile);
-
- }
-
-